<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Stream Chat</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
    <link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css">
    <link rel="stylesheet" href="/css/chat.css">
</head>
<body>
<div id="app" class="container mt-5">
    <div id="chatBox">
        <div v-for="message in messages" :key="message.id" :class="['message', message.isUser ? 'user-message' : 'ai-message']">
            <div v-html="message.content"></div>
            <div class="message-footer">
                <div class="message-actions" v-if="!message.isUser && !message.thinking">
                    <i class="bi bi-hand-thumbs-up" @click="likeMessage(message)" :class="{ 'liked': message.liked }" title="点赞"></i>
                    <i class="bi bi-hand-thumbs-down" @click="dislikeMessage(message)" :class="{ 'disliked': message.disliked }" title="不喜欢"></i>
                    <i class="bi bi-clipboard" @click="copyMessage(message)" title="复制"></i>
                    <i class="bi bi-arrow-clockwise" @click="retryMessage(message)" title="重试"></i>
                    <i class="bi bi-arrows-angle-expand" @click="expandMessage(message)" title="查看全文" v-if="message.content.length > 500"></i>
                </div>
                <small class="timestamp">{{ message.timestamp }}</small>
            </div>
        </div>
    </div>
    <form @submit.prevent="handleSubmit" class="mt-3">
        <div class="input-group">
            <input type="text" class="form-control" v-model="userInput" placeholder="输入您的问题..." 
                   :disabled="isProcessing" required>
            <button class="btn btn-primary" type="submit" :disabled="isProcessing || !userInput.trim()">
                <span v-if="isProcessing">
                    <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
                    {{ retryCount > 0 ? `重试中 (${retryCount}/3)` : '处理中...' }}
                </span>
                <span v-else>发送</span>
            </button>
        </div>
        <small class="text-muted" v-if="isProcessing">请耐心等待，正在处理您的请求...</small>
    </form>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://unpkg.com/element-plus"></script>
<script>
const app = Vue.createApp({
    data() {
        return {
            messages: [],
            userInput: '',
            isProcessing: false,
            errorMessage: '',
            retryCount: 0,
            eventSource: null,
            requestTimeout: null,
            toast: null,
            expandedMessageId: null
        };
    },
    mounted() {
        // 初始化 Toast
        this.toast = new bootstrap.Toast(document.getElementById('errorToast'), {
            delay: 2000
        });
    },
    methods: {
        showError(message) {
            ElementPlus.ElMessage.error(message);
        },
        appendMessage(content, isUser, error = false) {
            const timestamp = new Date().toLocaleString();
            const message = {
                id: Date.now() + Math.random(),
                content,
                isUser,
                timestamp,
                error,
                originalInput: isUser ? content : null
            };
            this.messages.push(message);
            this.$nextTick(() => {
                const chatBox = document.getElementById('chatBox');
                chatBox.scrollTop = chatBox.scrollHeight;
            });
            return message;
        },
        appendThinkingMessage() {
            const thinkingMessage = {
                id: 'thinking-' + Date.now(),
                content: '<div class="thinking-indicator"><div class="spinner"></div></div>',
                isUser: false,
                thinking: true,
                timestamp: new Date().toLocaleString()
            };
            this.messages.push(thinkingMessage);
            return thinkingMessage;
        },
        cleanupRequest() {
            if (this.eventSource) {
                this.eventSource.close();
                this.eventSource = null;
            }
            if (this.requestTimeout) {
                clearTimeout(this.requestTimeout);
                this.requestTimeout = null;
            }
            this.isProcessing = false;
            this.retryCount = 0;
        },
        handleError(error, message = null) {
            debugger
            console.error('Error:', error);
            const errorMsg = error || '请求失败，请稍后重试';
            this.showError(errorMsg);
            
            if (message) {
                // 将消息标记为出错状态
                const index = this.messages.findIndex(msg => msg.id === message.id);
                if (index !== -1) {
                    this.messages[index].error = true;
                    // 如果消息内容不包含错误提示，则添加
                    if (!this.messages[index].content.includes('error-message')) {
                        this.messages[index].content += '<div class="error-message">请求失败，点击<i class="bi bi-arrow-clockwise"></i>重试</div>';
                    }
                }
            }
            
            this.cleanupRequest();
        },
        async retryMessage(message) {
            if (this.isProcessing) {
                return;
            }
            
            // 找到当前消息的索引
            const currentIndex = this.messages.findIndex(msg => msg.id === message.id);
            if (currentIndex === -1) return;
            
            // 向前查找最近的用户消息
            let userMessageIndex = currentIndex - 1;
            while (userMessageIndex >= 0) {
                if (this.messages[userMessageIndex].isUser) {
                    break;
                }
                userMessageIndex--;
            }
            
            // 如果没有找到用户消息，返回
            if (userMessageIndex < 0) {
                this.showError('未找到对应的用户问题，无法重试');
                return;
            }
            
            const userMessage = this.messages[userMessageIndex];
            this.isProcessing = true;
            
            // 删除当前消息后的所有消息
            this.messages.splice(currentIndex);
            
            // 重新发送用户的原始问题
            await this.processUserInput(userMessage.content);
        },
        async processUserInput(userInput) {
            this.isProcessing = true;
            this.errorMessage = '';
            
            const thinkingMessage = this.appendThinkingMessage();
            let aiMessage = null;

            try {
                //this.eventSource = new EventSource(`/api/chat/stream?userInput=${encodeURIComponent(userInput)}`);
                this.eventSource = new EventSource(`/api/chat/assistant?userInput=${encodeURIComponent(userInput)}`);

                this.eventSource.onmessage = (event) => {
                    const message = JSON.parse(event.data);
                    
                    // 检查是否有错误信息
                    if (message.content && typeof message.content === 'string' && message.content.startsWith('{\"error\":')) {
                        try {
                            const errorObj = JSON.parse(message.content);
                            if (errorObj.error) {
                                // 删除思考中的消息
                                const thinkingIndex = this.messages.findIndex(msg => msg.id === thinkingMessage.id);
                                if (thinkingIndex !== -1) {
                                    this.messages.splice(thinkingIndex, 1);
                                }
                                
                                // 将错误信息作为AI消息显示，并标记为错误状态
                                aiMessage = this.appendMessage(`<div class="error-message">${errorObj.error}</div>`, false, true);
                                
                                // 显示错误提示
                                this.showError(errorObj.error);
                                return;
                            }
                        } catch (e) {
                            console.log('Not an error message, continuing with normal processing');
                        }
                    }
                    
                    // 处理AI消息
                    if (!message.isUser) {
                        if (!aiMessage) {
                            // 移除思考中的消息
                            const thinkingIndex = this.messages.findIndex(msg => msg.id === thinkingMessage.id);
                            if (thinkingIndex !== -1) {
                                this.messages.splice(thinkingIndex, 1);
                            }
                            
                            // 创建新的AI消息，初始状态为thinking
                            aiMessage = this.appendMessage(message.content || '', false);
                            aiMessage.thinking = true;
                        } else {
                            // 更新现有AI消息
                            const index = this.messages.findIndex(msg => msg.id === aiMessage.id);
                            if (index !== -1) {
                                const updatedMessage = {
                                    ...this.messages[index],
                                    content: (this.messages[index].content || '') + (message.content || ''),
                                    thinking: true  // 保持thinking状态
                                };
                                this.messages.splice(index, 1, updatedMessage);
                            }
                        }
                        
                        // 滚动到底部
                        this.$nextTick(() => {
                            const chatBox = document.getElementById('chatBox');
                            chatBox.scrollTop = chatBox.scrollHeight;
                        });
                    }
                };

                this.eventSource.onerror = (error) => {
                    // 如果状态是 CONNECTING (0) 且有 aiMessage，说明这是流正常结束的情况
                    if (this.eventSource && this.eventSource.readyState === 0 && aiMessage) {
                        this.isProcessing = false;
                        // 消息完成，移除thinking状态
                        const index = this.messages.findIndex(msg => msg.id === aiMessage.id);
                        if (index !== -1) {
                            this.messages[index].thinking = false;
                        }
                        this.cleanupRequest();
                        return;
                    }
                    
                    // 如果状态是 CLOSED，也认为是正常结束
                    if (this.eventSource && this.eventSource.readyState === 2) {
                        this.isProcessing = false;
                        // 消息完成，移除thinking状态
                        if (aiMessage) {
                            const index = this.messages.findIndex(msg => msg.id === aiMessage.id);
                            if (index !== -1) {
                                this.messages[index].thinking = false;
                            }
                        }
                        this.cleanupRequest();
                        return;
                    }
                    
                    console.error('EventSource error:', error);
                    if (thinkingMessage) {
                        // 删除思考中的消息
                        const thinkingIndex = this.messages.findIndex(msg => msg.id === thinkingMessage.id);
                        if (thinkingIndex !== -1) {
                            this.messages.splice(thinkingIndex, 1);
                        }
                    }
                    this.handleError(error, aiMessage);
                };

                this.eventSource.addEventListener('complete', () => {
                    this.isProcessing = false;
                    // 消息完成，移除thinking状态
                    if (aiMessage) {
                        const index = this.messages.findIndex(msg => msg.id === aiMessage.id);
                        if (index !== -1) {
                            this.messages[index].thinking = false;
                        }
                    }
                    this.cleanupRequest();
                });

            } catch (error) {
                // 删除思考中的消息
                const thinkingIndex = this.messages.findIndex(msg => msg.id === thinkingMessage.id);
                if (thinkingIndex !== -1) {
                    this.messages.splice(thinkingIndex, 1);
                }
                this.handleError(error, aiMessage);
            }
        },
        async handleSubmit() {
            if (this.isProcessing || !this.userInput.trim()) return;

            const userInput = this.userInput.trim();
            this.userInput = '';
            
            // 立即添加用户消息
            this.appendMessage(userInput, true);
            
            // 处理用户输入
            await this.processUserInput(userInput);
        },
        copyMessage(message) {
            const tempTextArea = document.createElement('textarea');
            tempTextArea.value = message.content.replace(/<[^>]*>/g, ''); // 移除HTML标签
            document.body.appendChild(tempTextArea);
            tempTextArea.select();
            document.execCommand('copy');
            document.body.removeChild(tempTextArea);
            
            ElementPlus.ElMessage.success('复制成功！');
        },
        
        expandMessage(message) {
            if (this.expandedMessageId === message.id) {
                this.expandedMessageId = null;
            } else {
                this.expandedMessageId = message.id;
            }
            this.$nextTick(() => {
                const chatBox = document.getElementById('chatBox');
                chatBox.scrollTop = chatBox.scrollHeight;
            });
        },
        likeMessage(message) {
            if (!message.isUser) {
                message.liked = !message.liked;
                if (message.liked) {
                    message.disliked = false;
                }
            }
        },
        dislikeMessage(message) {
            if (!message.isUser) {
                message.disliked = !message.disliked;
                if (message.disliked) {
                    message.liked = false;
                }
            }
        }
    },
    beforeUnmount() {
        this.cleanupRequest();
    }
});

app.use(ElementPlus);
app.mount('#app');
</script>
</body>
</html>